<template>
  <div class="page">
    <div>
      <el-button @click="outputPdf" type="primary">导出</el-button>
      <el-button @click="test" type="primary">测试</el-button>
    </div>
    <div id="pdfDom">
      <!-- 教育经历 -->
      <div class="education-list">
        <div class="title">教育经历</div>
        <div class="education-item">
          <div class="education-item-time">2016.09 - 2020.06</div>
          <div class="education-item-type">本科</div>
          <div class="education-item-school">成都大学</div>
          <div class="education-item-major">转件工程</div>
          <div class="education-item-ranking">专业排名1%~5%</div>
        </div>
        <div class="education-item">
          <div class="education-item-time">2016.09 - 2019.07</div>
          <div class="education-item-type">专科</div>
          <div class="education-item-school">四川中医药高等专科学校</div>
          <div class="education-item-major">护理助产</div>
          <div class="education-item-ranking">专业排名5%~20%</div>
        </div>
      </div>

      <!-- 校内经历 -->
      <div class="public-list">
        <div class="title">校内经历</div>
        <div class="list-item" v-for="(item, index) in 2" :key="index">
          <div class="header">
            <div class="header-time">2020.10 - 2020.10</div>
            <div class="header-name">成都妇女儿童中心医院</div>
            <div class="header-position">护理</div>
          </div>
          <div class="content">文章1984年出生于陕西省西安市。上高三的时候，文章被保送到四川师范大学艺术学院学习影视表演，但是他并未进入这个学校，而是决心去北京学习。在填写大学志愿之前，文章专门去北京考察了中国两大艺术院校—北京电影学院和中央戏剧学院。回到西安之后，文章不顾父母阻拦，将大学志愿从一本到专科总共八个志愿全部填成中央戏剧学院。2002年文章被中央戏剧学院表演系录取。</div>
        </div>
      </div>

      <!-- 工作经历 -->
      <div class="public-list" v-for="(item, idx) in 4" :key="idx">
        <div class="title">工作经历</div>
        <div class="list-item" v-for="(item, index) in 2" :key="index">
          <div class="header">
            <div class="header-time">2020.10 - 2020.10</div>
            <div class="header-name">成都妇女儿童中心医院</div>
            <div class="header-position">护理</div>
          </div>
          <div class="content">文章1984年出生于陕西省西安市。上高三的时候，文章被保送到四川师范大学艺术学院学习影视表演，但是他并未进入这个学校，而是决心去北京学习。在填写大学志愿之前，文章专门去北京考察了中国两大艺术院校—北京电影学院和中央戏剧学院。回到西安之后，文章不顾父母阻拦，将大学志愿从一本到专科总共八个志愿全部填成中央戏剧学院。2002年文章被中央戏剧学院表演系录取。</div>
        </div>
      </div>

      <!-- 项目经历 -->
      <div class="public-list">
        <div class="title">项目经历</div>
        <div class="list-item" v-for="(item, index) in 2" :key="index">
          <div class="header">
            <div class="header-time">2020.10 - 2020.10</div>
            <div class="header-name">成都妇女儿童中心医院</div>
            <div class="header-position">护理</div>
          </div>
          <div class="content">文章1984年出生于陕西省西安市。上高三的时候，文章被保送到四川师范大学艺术学院学习影视表演，但是他并未进入这个学校，而是决心去北京学习。在填写大学志愿之前，文章专门去北京考察了中国两大艺术院校—北京电影学院和中央戏剧学院。回到西安之后，文章不顾父母阻拦，将大学志愿从一本到专科总共八个志愿全部填成中央戏剧学院。2002年文章被中央戏剧学院表演系录取。</div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
export default {
  methods: {
    getPdfByWeb(title, dom) {
      // #pdfDom是要保存的页面元素
      return html2Canvas(document.querySelector(dom), {
        allowTaint: true,
        taintTest: false,
        useCORS: true,
        async: true,
        scale: '2',
        dpi: '192'
      }).then(function(canvas) {
        const contentWidth = canvas.width
        const contentHeight = canvas.height
        // 一页pdf显示html页面生成的canvas高度;
        const pageHeight = Math.ceil(contentWidth / 595.28 * 841.89)
        // 未生成pdf的html页面高度
        let leftHeight = contentHeight
        // pdf页面偏移
        let position = 0
        // a4纸的尺寸[595.28,841.89]，html页面生成的canvas在pdf中图片的宽高
        const imgWidth = 595.28
        const imgHeight = 595.28 / contentWidth * contentHeight
        // console.log(canvas)
        const pageData = canvas.toDataURL('image/jpeg/png', 1)
        const PDF = new JsPDF('', 'pt', 'a4', true)
        // console.log(PDF)
        // 有两个高度需要区分，一个是html页面的实际高度，和生成pdf的页面高度(841.89)
        // 当内容未超过pdf一页显示的范围，无需分页
        if (leftHeight < pageHeight) {
          PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
        } else {
          while (leftHeight > 0) {
            PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
            leftHeight -= pageHeight
            position -= 841.89
            // 避免添加空白页
            if (leftHeight > 0) {
              PDF.addPage()
            }
          }
        }
        PDF.save(title + '.pdf')
        return PDF.output('datauristring')
      })
    },
    outputPdf () {
      // 验证分页被切割的问题
      const A4_WIDTH = 592.28; // A4纸宽度
      const A4_HEIGHT = 841.89; // A4纸高度
      // $myLoading 自定义等待动画组件，实现导出事件的异步等待交互
      this.$nextTick(() => {
        let target = document.getElementById('pdfDom')
        // scrollWidth: 元素内容宽度(包括由于overflow溢出而在屏幕上不可见的内容)
        let pageHeight = target.scrollWidth / A4_WIDTH * A4_HEIGHT
        // 获取分割dom，此处为class类名为public-list的dom
        let lableListID = document.getElementsByClassName('public-list')
        // 进行分割操作，当dom内容已超出a4的高度，则将该dom前插入一个空dom，把他挤下去，分割
        for (let i = 0; i < lableListID.length; i++) {
          // offsetTop：相对于父元素的顶部内边距的距离
          // offsetHeight：元素的像素高度(包含元素的垂直内边距和边框 => 整数)
          let multiple = Math.ceil((lableListID[i].offsetTop + lableListID[i].offsetHeight) / pageHeight);
          if (this.isSplit(lableListID, i, multiple * pageHeight)) {
            let divParent = lableListID[i].parentNode; // 获取该div的父节点
            let newNode = document.createElement('div');
            newNode.className = 'emptyDiv';
            newNode.style.background = '#ffffff';
            let _H = multiple * pageHeight - (lableListID[i].offsetTop + lableListID[i].offsetHeight);
            newNode.style.height = _H + 30 + 'px';
            newNode.style.width = '100%';
            let next = lableListID[i].nextSibling; // 获取div的下一个兄弟节点
            // 判断兄弟节点是否存在
            if (next) {
              // 存在则将新节点插入到div的下一个兄弟节点之前，即div之后
              divParent.insertBefore(newNode, next);
            } else {
              // 不存在则直接添加到最后,appendChild默认添加到divParent的最后
              divParent.appendChild(newNode);
            }
          }
        }
        // 传入title和dom标签，此处是 #content
        // 异步函数，导出成功后处理交互
        // this.getPdf('巡检报告单', '#pdfDom')
        this.getPdfByWeb('巡检报告单', '#pdfDom').then(res => {
          console.log(res)
        })
      });
      
      // 不验证分页被切割的问题
      // this.getPdfByWeb('巡检报告单', '#pdfDom').then(res => {
      //   console.log(res)
      // })
    },
    // 计算当前这块dom是否跨越了a4大小，以此分割
    isSplit (nodes, index, pageHeight) {
      if (nodes[index].offsetTop + nodes[index].offsetHeight < pageHeight && nodes[index + 1] && nodes[index + 1].offsetTop + nodes[index + 1].offsetHeight > pageHeight) {
        return true
      }
      return false
    },
    test () {
      let target = document.getElementById('pdfDom')
      console.log(target.scrollWidth)
    }
  },
}
</script>

<style lang="scss">
$border: 1px solid #eee;
.page {
  width: 100%;
  height: 100%;
  // display: flex;
  // justify-content: center;
  // align-items: center;
  // flex-direction: column;
  background: #ccc;
  overflow: auto;
  #pdfDom {
    width: 800px;
    // height: 400px;
    height: auto;
    // overflow: hidden;
    background: #fff;
    padding: 60px;
    .title {
      color: #333;
      font-family: PingFangSC-Medium,PingFang SC;
      font-size: 20px;
      font-weight: 500;
      position: relative;
      border-left: 5px solid #32ca99;
      padding-left: 10px;
      margin-bottom: 10px;
    }
    .education-list {
      border-top: $border;
      border-bottom: $border;
      padding: 15px 0;
      .education-item {
        line-height: 26px;
        display: flex;
        .education-item-time,
        .education-item-type,
        .education-item-school,
        .education-item-major,
        .education-item-ranking {
          font-size: 16px;
          font-weight: 500;
          margin-right: 20px;
        }
      }
    }
    // 公用list
    .public-list {
      border-bottom: $border;
      padding: 15px 0;
      .list-item {
        .header {
          display: flex;
          line-height: 25px;
          font-weight: 600;
          font-size: 16px;
          .header-time,
          .header-name,
          .header-position {
            margin-right: 20px;
          }
        }
        .content {
          line-height: 19px;
          font-size: 14px;
          font-weight: 500;
          text-align: justify;
          color: #666;
        }
        margin-bottom: 10px;
      }
    }
  }
}
</style>